#ifndef _BUOLA_GL_CBUFFER_H_
#define _BUOLA_GL_CBUFFER_H_

#include <buola/gl.h>

namespace buola { namespace gl {

class CBuffer
{
public:
    CBuffer()
        :   mID(0)
    {}

    CBuffer(const CBuffer&)=delete;

    CBuffer(CBuffer &&pO)
        :   mID(pO.mID)
    {
        pO.mID=0;
    }
    
    ~CBuffer()
    {
        if(mID) Delete();
    }

    CBuffer &operator=(const CBuffer&)=delete;

    CBuffer &operator=(CBuffer &&pO)
    {
        std::swap(mID,pO.mID);
        return *this;
    }

    void Create(GLenum pTarget,GLsizeiptr pSize)
    {
        //always delete it and create it again, since it is unusual to recycle buffers anyway and opengl seems to
        //optimize based on first usage
        if(mID) Delete();
        glGenBuffers(1,&mID);
        mTarget=pTarget;
        mSize=pSize;
        glBindBuffer(pTarget,mID);
        glBufferData(pTarget,pSize,nullptr,GL_DYNAMIC_DRAW);
    }

    void Data(const void *pData,GLsizeiptr pSize)
    {
        glBufferData(mTarget,pSize,pData,GL_DYNAMIC_DRAW);
    }

    template<typename tType>
    void Data(const std::vector<tType> &pVector)
    {
        Data(pVector.data(),sizeof(tType)*pVector.size());
    }

    void SubData(const void *pData,GLsizeiptr pSize,GLintptr pOffset=0)
    {
        glBufferSubData(mTarget,pOffset,pSize,pData);
    }
    
    template<typename tType>
    void SubData(const std::vector<tType> &pVector,GLintptr pOffset=0)
    {
        SubData(pVector.data(),sizeof(tType)*pVector.size(),pOffset);
    }

    void Bind()
    {
        glBindBuffer(mTarget,mID);
    }

    void Unbind()
    {
        glBindBuffer(mTarget,0);
    }

    void Delete()
    {
        glDeleteFramebuffers(1,&mID);
        mID=0;
    }

    explicit operator bool()    {   return mID; }

    GLuint ID() const       {   return mID;     }
    GLenum Target() const   {   return mTarget; }
    GLsizeiptr size() const {   return mSize;   }

private:
    GLuint mID;
    GLsizeiptr mSize;
    GLenum mTarget;
};

/*namespace gl*/ } /*namespace buola*/ }

#endif
